/*
 * Copyright (C) 2012 POAS.VSTU
 */
package ui;

import java.awt.Color;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import model.*;


/**
 * Игровая панель игры, в пределах которой идет игровой процесс и перемещаются карты
 * @author POAS
 */
public class UIGamePanel extends JPanel implements GameEventListener {
    
   // Размеры панели
    private static final int WIDTH = 983;
    private static final int HEIGHT = 866;
    
    // Фон
    private static final String BACKGROUND_IMAGE_FILE = "./src/images/frame/background.jpg";
    
    // Задержка между кадрами при движени карт; влияет на 
    // скорость перемещения карт (но не на кол-во кадров)
    public static final int TIME_MOVE_STEP_MS = 2;
    
    /** Модель игры*/
    private GameModel           mModel;
    /** Отбой */
    private UICardPileRecycle   mCardPileRecycle;
    /** Кон */
    private UICardPileKitty     mCardPileKitty;
    /** Колода карт */
    private UICardStack         mCardStack;
    /** Карта, которая не раздается игрокам */
    private UICardPile          mExtraCardPile;
    
    // Игроки, начиная от игрока-человека по часовой стрелке
    private ArrayList<UIPlayer> mPlayers;
    
    // Карта соответствия между моделью карт (Card) и их представлением (UICard)
    private HashMap<Card, UICard> mModelToUICards;
    //Карта соответствия между моделью стопок карт (CardPile) и их представлением (UICardPile)
    private HashMap<CardPile, UICardPile> mModelToUICardPiles;
    
    
    private ActionScript movementScript = new ActionScript(this);
    
    /**
     * Конструктр
     */
    public UIGamePanel() {
        
        this.setLayout(null);
        
        mModelToUICards = new HashMap<>();
        mModelToUICardPiles = new HashMap<>();
        
        mModel = new GameModel();
        mModel.addGameEventListener(this);
        
        mCardPileRecycle = new UICardPileRecycle(mModel.getRecycle(), this);
        mCardPileRecycle.setLocation(30, 30);
        mCardPileRecycle.setOrientation(Orientation.ROTATED_CLOCKWISE);
        mModelToUICardPiles.put(mModel.getRecycle(), mCardPileRecycle);
        
        mCardPileKitty = new UICardPileKitty(mModel.getKitty(), this);
        mModelToUICardPiles.put(mModel.getKitty(), mCardPileKitty);
        
        // создание и настройка колоды
        mCardStack = new UICardStack(mModel.getStack(), this); 
        mCardStack.setLocation(480, 310); 
        mModelToUICardPiles.put(mModel.getStack(), mCardStack);
        
        mExtraCardPile = new UICardPile(mModel.getExtraCards(), this);
        mExtraCardPile.setLocation(50, 580);
        mModelToUICardPiles.put(mModel.getExtraCards(), mExtraCardPile);
       
        
        // Создаем игроков
        mPlayers = new ArrayList<>();
        UIPlayer newPlayer;
        int numRotate = 0;
        for(Object player: mModel.getAllPlayers().toArray()) {
             newPlayer = new UIPlayer((Player)player, this);
             mPlayers.add(newPlayer);
             newPlayer.rotate(numRotate);
             mModelToUICardPiles.put(((Player)player).getCards(), newPlayer.getUICardPile());
             numRotate++;
        }
        
        // устанавливаем позиции игроков (пока что для пробы)
        Iterator iterUIPlayers = mPlayers.iterator();
        ((UIPlayer) iterUIPlayers.next()).setLocation(new Point(470, 655));
        ((UIPlayer) iterUIPlayers.next()).setLocation(new Point(180, 336));
        ((UIPlayer) iterUIPlayers.next()).setLocation(new Point(470, 22));
        ((UIPlayer) iterUIPlayers.next()).setLocation(new Point(805, 336));
        
        
        Thread tModel = new Thread(mModel);
        tModel.start();
        
        // добавляем фоновое изображение
        JLabel bgLabel = new javax.swing.JLabel();
        bgLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        bgLabel.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(102, 102, 102), 1, true));
        ImageIcon bgIcon = new ImageIcon(BACKGROUND_IMAGE_FILE);
        System.out.print(bgIcon.getIconHeight());
        bgLabel.setIcon(bgIcon);
        bgLabel.setBounds(0, 0, getWidth(), getHeight());
        add(bgLabel);
      
    }
    
    /** Получить модель игры */
    public GameModel getModel() {
        return mModel;
    }
    
    /** Получить ширину игрового поля */
    @Override
    public int getWidth() {
        return WIDTH;
    }
    
    /** Получить высоту игрового поля */
    @Override
    public int getHeight() {
        return HEIGHT;
    }
    
    /** Создать UI карту */
    UICard createUICard(Card card) {
        if (mModelToUICards.containsKey(card)) {
            throw new UnsupportedOperationException("Попытка создание представления "
                    + "карты, совпадающей уже с имеющейся");
        }
        
        UICard uiCard = new UICard(card, this);
        mModelToUICards.put(card, uiCard);
       
        return uiCard;
    }
    
    /** 
     * Получить UI-карту 
     * @param card Карта из модели игры
     */
    UICard getUICard(Card card) {
        if (!mModelToUICards.containsKey(card)) {
            throw new UnsupportedOperationException("Попытка получить несуществующую "
                    + "UI карту");
        }
        
        return mModelToUICards.get(card);
    }
    
        /** 
     * Получить UI-стопку карту 
     * @param cardPile Стопка карт из модели игры
     */
    UICardPile getUICardPile(CardPile cardPile) {
        if (!mModelToUICardPiles.containsKey(cardPile)) {
            throw new UnsupportedOperationException("Попытка получить несуществующую "
                    + "UI стопку карт");
        }
        
        return mModelToUICardPiles.get(cardPile);
    }
  
    
    /**
     * Управление возможностью воздействовать на игровое поле игроком
     * @param isEnabled - true, чтобы игроку были доступны все действия над игровым полем  
     */
    private void enableUserActions(boolean isEnabled) {
    
    }
    
    void sleep() throws InterruptedException {
        sleep(TIME_MOVE_STEP_MS);
    }
    
    void sleep(int ms) throws InterruptedException {
        Thread.sleep(ms);
    }
    
    @Override
    public void cardsMoved(GameEvent e) {
 
        UICardPile uiCardPile = getUICardPile(e.getCardPileTo());
        
        // получаем перемещаемые карты
        ArrayList<UICard> listUIcards = new ArrayList();
        for(Card card: e.getCards()) {
            listUIcards.add(getUICard(card));
        }

        uiCardPile.dragIn(e.getCards());
        
    }

    @Override
    public void cardsExtracted(GameEvent e) {
        UICardPile uiCardPile = getUICardPile(e.getCardPileFrom());
       
        uiCardPile.pop(e.getCards());
    }

    @Override
    public void cardsAdded(GameEvent e) {
        //System.out.println("cardsAdded");
        //throw new UnsupportedOperationException("Not supported yet.");
        
        UICardPile uiCardPile = getUICardPile(e.getCardPileTo());
        
        uiCardPile.push(e.getCards());
    }

    void addMovement(Action movement) {
        movementScript.addMovement(movement, 0);
    }

    void executeMovements() throws InterruptedException {
        movementScript.execute(); 
    }

    @Override
    public void userActionWaitStart() {
        try {
            movementScript.execute();
        } catch (InterruptedException ex) {
            Logger.getLogger(UIGamePanel.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public void allCardsInStack() {
        movementScript.addSyncMoment();
    }
}